package cn.enilu.flash.service.zhifu;

import cn.enilu.flash.bean.entity.shop.Order;
import cn.enilu.flash.bean.entity.shop.OrderRefund;
import cn.enilu.flash.bean.entity.shop.ShopUser;
import cn.enilu.flash.bean.enumeration.shop.OrderEnum;
import cn.enilu.flash.bean.vo.front.Rets;
import cn.enilu.flash.service.shop.OrderService;
import cn.enilu.flash.utils.HttpUtil;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.io.IOUtils;
import org.nutz.json.Json;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.ssssssss.magicapi.core.service.MagicAPIService;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信支付
 * @author ：enilu
 * @date ：Created in 2020/3/17 20:26
 */
@Service
public class WeixinPayService {

    private static String refundUrl;
    @Value("${wx.pay.refundUrl:}")
    public void setLicenseCompany(String refundUrl){
        WeixinPayService.refundUrl = refundUrl;
    }

    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private OrderService orderService;

    @Autowired
    MagicAPIService service;
    private Logger logger = LoggerFactory.getLogger(WeixinPayService.class);
    public WxPayMpOrderResult prepare(ShopUser user, Order order){

        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderRequest.setOutTradeNo(order.getOrderSn());
        orderRequest.setOpenid(user.getWechatOpenId());
        orderRequest.setBody("商城订单：" + order.getOrderSn());
        BigDecimal totalPrice = order.getTotalPrice();
        orderRequest.setTotalFee(totalPrice.intValue());
        orderRequest.setSpbillCreateIp(HttpUtil.getIp());


        try {
            WxPayMpOrderResult result = wxPayService.createOrder(orderRequest);
            orderService.startPay(order);
            return  result;
        } catch (WxPayException e) {
            logger.error("微信支付异常",e);
        }
        return null;
    }

    public String resultNotify() {
        String xmlResult = null;
        try {
            HttpServletRequest request = HttpUtil.getRequest();
            xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
        } catch (IOException e) {
            logger.error("解析微信支付结果通知异常",e);
            return WxPayNotifyResponse.fail(e.getMessage());
        }

        WxPayOrderNotifyResult result = null;
        try {
            result = wxPayService.parseOrderNotifyResult(xmlResult);

            if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getResultCode())){
                logger.error(xmlResult);
                throw new WxPayException("微信通知支付失败！");
            }
            if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getReturnCode())){
                logger.error(xmlResult);
                throw new WxPayException("微信通知支付失败！");
            }
        } catch (WxPayException e) {
            e.printStackTrace();
            return WxPayNotifyResponse.fail(e.getMessage());
        }

        logger.info("处理腾讯支付平台的订单支付", Json.toJson(result));

        String orderSn = result.getOutTradeNo();
        String payId = result.getTransactionId();

        Integer totalFee =  result.getTotalFee();
        Order order = orderService.getByOrderSn(orderSn);
        if (order == null) {
            return WxPayNotifyResponse.fail("订单不存在 sn=" + orderSn);
        }
        // 检查这个订单是否已经处理过
        if (order.hasPayed()) {
            return WxPayNotifyResponse.success("订单已经处理成功!");
        }
        // 检查支付订单金额
        if (totalFee.intValue()!=order.getTotalPrice().intValue()) {
            return WxPayNotifyResponse.fail(order.getOrderSn() + " : 支付金额不符合 totalFee=" + totalFee);
        }

        order.setPayId(payId);
        orderService.paySuccess(order, OrderEnum.PayTypeEnum.UN_SEND.getKey());

        //传送订单信息到CRM
        Map<String, Object> params = new HashMap<>();
        params.put("orderSn", order.getOrderSn());
        Object value = service.execute("POST", "/order/syncCrm", params);
        logger.info("CRM同步结果",value.toString());


        return WxPayNotifyResponse.success("支付成功！");
    }

    public Object refund( Order order){
        WxPayRefundRequest request = new WxPayRefundRequest();
        request.setOutTradeNo(order.getOrderSn());
        request.setOutRefundNo(order.getOrderSn() + "-01");
        request.setRefundFee(order.getTotalPrice().intValue());
        request.setTotalFee(order.getTotalPrice().intValue());
        request.setNotifyUrl(refundUrl);

        try {
            WxPayRefundResult result = wxPayService.refund(request);
            orderService.refund(order);
            return Rets.success("success");
        } catch (WxPayException e) {
            logger.error("微信支付异常",e);
            return Rets.failure(e.getMessage());
        }
    }

    public String refundNotify(String xmlData) {

        WxPayRefundNotifyResult result = null;
        try {
            result = wxPayService.parseRefundNotifyResult(xmlData);
            logger.info("退款返回信息");
            logger.info(result.toString());
            if(result.getReturnCode().equals("SUCCESS")) {
                String orderNo = result.getReqInfo().getOutTradeNo();
                String refundNo = result.getReqInfo().getOutRefundNo();
                Order order = orderService.getByOrderSn(orderNo);
                orderService.refundEnd(order);
            }

        }catch (WxPayException e){
            e.printStackTrace();
            return WxPayNotifyResponse.fail(e.getMessage());
        }
        return WxPayNotifyResponse.success("");
    }
}
